use wasm_bindgen::prelude::*;
use serde::{Deserialize, Serialize};
use web_sys::console;

/// WebAssembly演示 - 展示Rust在Web开发中的优势
/// 包括：高性能计算、内存安全、与JavaScript互操作

// 当wasm模块被加载时调用
#[wasm_bindgen(start)]
pub fn main() {
    console_error_panic_hook::set_once();
    console::log_1(&"🚀 Rust WebAssembly模块已加载".into());
}

// 数学计算器
#[wasm_bindgen]
pub struct Calculator {
    history: Vec<String>,
}

#[wasm_bindgen]
impl Calculator {
    #[wasm_bindgen(constructor)]
    pub fn new() -> Calculator {
        Calculator {
            history: Vec::new(),
        }
    }
    
    #[wasm_bindgen]
    pub fn add(&mut self, a: f64, b: f64) -> f64 {
        let result = a + b;
        self.history.push(format!("{} + {} = {}", a, b, result));
        result
    }
    
    #[wasm_bindgen]
    pub fn multiply(&mut self, a: f64, b: f64) -> f64 {
        let result = a * b;
        self.history.push(format!("{} × {} = {}", a, b, result));
        result
    }
    
    #[wasm_bindgen]
    pub fn get_history(&self) -> String {
        self.history.join("\n")
    }
    
    #[wasm_bindgen]
    pub fn clear_history(&mut self) {
        self.history.clear();
    }
}

// 图像处理器
#[wasm_bindgen]
pub struct ImageProcessor {
    width: u32,
    height: u32,
    data: Vec<u8>,
}

#[wasm_bindgen]
impl ImageProcessor {
    #[wasm_bindgen(constructor)]
    pub fn new(width: u32, height: u32) -> ImageProcessor {
        let size = (width * height * 4) as usize; // RGBA
        ImageProcessor {
            width,
            height,
            data: vec![0; size],
        }
    }
    
    #[wasm_bindgen]
    pub fn get_data(&self) -> Vec<u8> {
        self.data.clone()
    }
    
    #[wasm_bindgen]
    pub fn set_pixel(&mut self, x: u32, y: u32, r: u8, g: u8, b: u8, a: u8) {
        if x < self.width && y < self.height {
            let index = ((y * self.width + x) * 4) as usize;
            self.data[index] = r;
            self.data[index + 1] = g;
            self.data[index + 2] = b;
            self.data[index + 3] = a;
        }
    }
    
    #[wasm_bindgen]
    pub fn apply_grayscale(&mut self) {
        for i in (0..self.data.len()).step_by(4) {
            let r = self.data[i] as f32;
            let g = self.data[i + 1] as f32;
            let b = self.data[i + 2] as f32;
            
            let gray = (0.299 * r + 0.587 * g + 0.114 * b) as u8;
            
            self.data[i] = gray;
            self.data[i + 1] = gray;
            self.data[i + 2] = gray;
        }
    }
    
    #[wasm_bindgen]
    pub fn apply_blur(&mut self, radius: u32) {
        let mut new_data = self.data.clone();
        
        for y in 0..self.height {
            for x in 0..self.width {
                let mut r_sum = 0u32;
                let mut g_sum = 0u32;
                let mut b_sum = 0u32;
                let mut count = 0u32;
                
                for dy in -(radius as i32)..=(radius as i32) {
                    for dx in -(radius as i32)..=(radius as i32) {
                        let nx = x as i32 + dx;
                        let ny = y as i32 + dy;
                        
                        if nx >= 0 && nx < self.width as i32 && ny >= 0 && ny < self.height as i32 {
                            let index = ((ny * self.width as i32 + nx) * 4) as usize;
                            r_sum += self.data[index] as u32;
                            g_sum += self.data[index + 1] as u32;
                            b_sum += self.data[index + 2] as u32;
                            count += 1;
                        }
                    }
                }
                
                let index = ((y * self.width + x) * 4) as usize;
                new_data[index] = (r_sum / count) as u8;
                new_data[index + 1] = (g_sum / count) as u8;
                new_data[index + 2] = (b_sum / count) as u8;
            }
        }
        
        self.data = new_data;
    }
}

// 数据处理器
#[derive(Serialize, Deserialize)]
struct DataPoint {
    x: f64,
    y: f64,
    value: f64,
}

#[wasm_bindgen]
pub struct DataProcessor {
    data: Vec<DataPoint>,
}

#[wasm_bindgen]
impl DataProcessor {
    #[wasm_bindgen(constructor)]
    pub fn new() -> DataProcessor {
        DataProcessor {
            data: Vec::new(),
        }
    }
    
    #[wasm_bindgen]
    pub fn add_point(&mut self, x: f64, y: f64, value: f64) {
        self.data.push(DataPoint { x, y, value });
    }
    
    #[wasm_bindgen]
    pub fn get_data_json(&self) -> String {
        serde_json::to_string(&self.data).unwrap_or_else(|_| "[]".to_string())
    }
    
    #[wasm_bindgen]
    pub fn calculate_statistics(&self) -> String {
        if self.data.is_empty() {
            return "{}".to_string();
        }
        
        let count = self.data.len();
        let sum: f64 = self.data.iter().map(|p| p.value).sum();
        let mean = sum / count as f64;
        
        let variance: f64 = self.data.iter()
            .map(|p| (p.value - mean).powi(2))
            .sum::<f64>() / count as f64;
        let std_dev = variance.sqrt();
        
        let min = self.data.iter().map(|p| p.value).fold(f64::INFINITY, f64::min);
        let max = self.data.iter().map(|p| p.value).fold(f64::NEG_INFINITY, f64::max);
        
        let stats = serde_json::json!({
            "count": count,
            "sum": sum,
            "mean": mean,
            "std_dev": std_dev,
            "min": min,
            "max": max
        });
        
        stats.to_string()
    }
    
    #[wasm_bindgen]
    pub fn clear_data(&mut self) {
        self.data.clear();
    }
}

// 游戏引擎组件
#[wasm_bindgen]
pub struct GameEngine {
    entities: Vec<Entity>,
    width: f64,
    height: f64,
}

#[derive(Clone)]
struct Entity {
    id: u32,
    x: f64,
    y: f64,
    vx: f64,
    vy: f64,
    radius: f64,
    color: String,
}

#[wasm_bindgen]
impl GameEngine {
    #[wasm_bindgen(constructor)]
    pub fn new(width: f64, height: f64) -> GameEngine {
        GameEngine {
            entities: Vec::new(),
            width,
            height,
        }
    }
    
    #[wasm_bindgen]
    pub fn add_entity(&mut self, x: f64, y: f64, radius: f64, color: &str) -> u32 {
        let id = self.entities.len() as u32;
        self.entities.push(Entity {
            id,
            x,
            y,
            vx: 0.0,
            vy: 0.0,
            radius,
            color: color.to_string(),
        });
        id
    }
    
    #[wasm_bindgen]
    pub fn set_velocity(&mut self, id: u32, vx: f64, vy: f64) {
        if let Some(entity) = self.entities.iter_mut().find(|e| e.id == id) {
            entity.vx = vx;
            entity.vy = vy;
        }
    }
    
    #[wasm_bindgen]
    pub fn update(&mut self, dt: f64) {
        for entity in &mut self.entities {
            entity.x += entity.vx * dt;
            entity.y += entity.vy * dt;
            
            // 边界碰撞检测
            if entity.x - entity.radius < 0.0 || entity.x + entity.radius > self.width {
                entity.vx = -entity.vx;
                entity.x = entity.x.max(entity.radius).min(self.width - entity.radius);
            }
            if entity.y - entity.radius < 0.0 || entity.y + entity.radius > self.height {
                entity.vy = -entity.vy;
                entity.y = entity.y.max(entity.radius).min(self.height - entity.radius);
            }
        }
    }
    
    #[wasm_bindgen]
    pub fn get_entities_json(&self) -> String {
        let entities_data: Vec<serde_json::Value> = self.entities.iter().map(|e| {
            serde_json::json!({
                "id": e.id,
                "x": e.x,
                "y": e.y,
                "radius": e.radius,
                "color": e.color
            })
        }).collect();
        
        serde_json::to_string(&entities_data).unwrap_or_else(|_| "[]".to_string())
    }
}

// 工具函数
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u32 {
    match n {
        0 => 0,
        1 => 1,
        _ => {
            let mut a = 0;
            let mut b = 1;
            for _ in 2..=n {
                let temp = a + b;
                a = b;
                b = temp;
            }
            b
        }
    }
}

#[wasm_bindgen]
pub fn prime_check(n: u32) -> bool {
    if n < 2 {
        return false;
    }
    if n == 2 {
        return true;
    }
    if n % 2 == 0 {
        return false;
    }
    
    let sqrt_n = (n as f64).sqrt() as u32;
    for i in (3..=sqrt_n).step_by(2) {
        if n % i == 0 {
            return false;
        }
    }
    true
}

#[wasm_bindgen]
pub fn sort_array(mut arr: Vec<i32>) -> Vec<i32> {
    arr.sort();
    arr
}

// 性能测试
#[wasm_bindgen]
pub fn performance_test(iterations: u32) -> String {
    let start = js_sys::Date::now();
    
    // 执行一些计算密集型任务
    let mut sum = 0.0;
    for i in 0..iterations {
        sum += (i as f64).sqrt().sin().cos();
    }
    
    let end = js_sys::Date::now();
    let duration = end - start;
    
    format!("执行 {} 次迭代耗时: {:.2}ms, 结果: {:.6}", iterations, duration, sum)
}

// 导出到全局作用域
#[wasm_bindgen]
pub fn setup_demo() {
    let window = web_sys::window().unwrap();
    let document = window.document().unwrap();
    
    // 创建演示界面
    if let Some(body) = document.body() {
        let title = document.create_element("h1").unwrap();
        title.set_text_content(Some("🚀 Rust WebAssembly 演示"));
        body.append_child(&title).unwrap();
        
        let description = document.create_element("p").unwrap();
        description.set_text_content(Some("这个演示展示了Rust在WebAssembly中的强大功能：高性能计算、内存安全、与JavaScript的无缝互操作。"));
        body.append_child(&description).unwrap();
        
        // 创建计算器演示
        let calc_div = document.create_element("div").unwrap();
        calc_div.set_inner_html(r#"
            <h2>🧮 计算器</h2>
            <input type="number" id="calc-a" placeholder="数字 A" value="10">
            <input type="number" id="calc-b" placeholder="数字 B" value="5">
            <button onclick="calcDemo()">计算</button>
            <div id="calc-result"></div>
            <div id="calc-history"></div>
        "#);
        body.append_child(&calc_div).unwrap();
        
        // 创建性能测试演示
        let perf_div = document.create_element("div").unwrap();
        perf_div.set_inner_html(r#"
            <h2>⚡ 性能测试</h2>
            <input type="number" id="perf-iterations" placeholder="迭代次数" value="1000000">
            <button onclick="perfTest()">运行测试</button>
            <div id="perf-result"></div>
        "#);
        body.append_child(&perf_div).unwrap();
        
        // 创建数学函数演示
        let math_div = document.create_element("div").unwrap();
        math_div.set_inner_html(r#"
            <h2>🔢 数学函数</h2>
            <input type="number" id="fib-n" placeholder="斐波那契数列项数" value="20">
            <button onclick="fibDemo()">计算斐波那契</button>
            <input type="number" id="prime-n" placeholder="质数检查" value="17">
            <button onclick="primeDemo()">检查质数</button>
            <div id="math-result"></div>
        "#);
        body.append_child(&math_div).unwrap();
    }
}

// JavaScript绑定函数
#[wasm_bindgen]
pub fn calc_demo() -> String {
    let mut calc = Calculator::new();
    let result1 = calc.add(10.0, 5.0);
    let result2 = calc.multiply(3.0, 4.0);
    let result3 = calc.add(result1, result2);
    
    format!("10 + 5 = {}\n3 × 4 = {}\n{} + {} = {}\n\n历史记录:\n{}", 
            result1, result2, result1, result2, result3, calc.get_history())
}

#[wasm_bindgen]
pub fn fib_demo(n: u32) -> String {
    let result = fibonacci(n);
    format!("斐波那契数列第 {} 项: {}", n, result)
}

#[wasm_bindgen]
pub fn prime_demo(n: u32) -> String {
    let is_prime = prime_check(n);
    format!("{} {} 质数", n, if is_prime { "是" } else { "不是" })
}

#[wasm_bindgen]
pub fn perf_demo(iterations: u32) -> String {
    performance_test(iterations)
}
